﻿using System;
using System.Threading.Tasks;
using System.Windows.Navigation;
using System.Windows.Threading;
using Newtonsoft.Json;
using SocialApi.Core.Request;
using SocialApi.Instagram;
using SocialApi.Instagram.AppSettings;
using SocialApi.Instagram.Entities.Methods.Relationships;
using SocialApi.TestApp.Models;

namespace SocialApi.TestApp.ViewModels
{
    public class InstagramViewModel : ViewModelBase
    {
        #region Настройка

        private readonly InstagramService _instagram;

        public string Url
        {
            get { return _url; }
            set
            {
                _url = value;
                OnPropertyChanged();
            }
        }
        private string _url;

        public string Result
        {
            get { return _result; }
            set
            {
                _result = value;
                OnPropertyChanged();
            }
        }
        private string _result;

        #region Параметры запроса

        public long UserId
        {
            get { return _userId; }
            set
            {
                _userId = value;
                OnPropertyChanged();
            }
        }
        private long _userId;

        public long UserId2
        {
            get { return _userId2; }
            set
            {
                _userId2 = value;
                OnPropertyChanged();
            }
        }
        private long _userId2;

        public long MediaId
        {
            get { return _mediaId; }
            set
            {
                _mediaId = value;
                OnPropertyChanged();
            }
        }
        private long _mediaId;

        public long LocationId
        {
            get { return _locationId; }
            set
            {
                _locationId = value;
                OnPropertyChanged();
            }
        }
        private long _locationId;

        public int Distance
        {
            get { return _distance; }
            set
            {
                _distance = value;
                OnPropertyChanged();
            }
        }
        private int _distance;

        public DateTime MaxTime
        {
            get { return _maxTime; }
            set
            {
                _maxTime = value;
                OnPropertyChanged();
            }
        }
        private DateTime _maxTime;

        public DateTime MinTime
        {
            get { return _minTime; }
            set
            {
                _minTime = value;
                OnPropertyChanged();
            }
        }
        private DateTime _minTime;

        public double Lng
        {
            get { return _lng; }
            set
            {
                _lng = value;
                OnPropertyChanged();
            }
        }
        private double _lng;

        public double Lat
        {
            get { return _lat; }
            set
            {
                _lat = value;
                OnPropertyChanged();
            }
        }
        private double _lat;

        public string TagName
        {
            get { return _tagName; }
            set
            {
                _tagName = value;
                OnPropertyChanged();
            }
        }
        private string _tagName;

        public string Search
        {
            get { return _search; }
            set
            {
                _search = value;
                OnPropertyChanged();
            }
        }
        private string _search;

        private ApiInfo _apiInfo;

        public string UserIdText { get; private set; }

        public string UserId2Text { get; private set; }

        public string MediaIdText { get; private set; }

        public string TagNameText { get; private set; }

        public string LocationIdText { get; private set; }

        public string DistanceText { get; private set; }

        public string MinTimeText { get; private set; }

        public string MaxTimeText { get; private set; }

        public string LngText { get; private set; }

        public string LatText { get; private set; }

        public string SearchText { get; private set; }

        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                _isEnabled = value;
                OnPropertyChanged();
            }
        }
        private bool _isEnabled;

        #endregion

        private string _commandParameter;

        /// <summary>
        /// Модель Instagram'а
        /// </summary>
        /// <param name="dispatcher">Текущий <see cref="Dispatcher"/></param>
        /// <param name="navigationService">Текущий <see cref="NavigationService"/></param>
        /// <param name="url">URL  с ответом от сервера</param>
        public InstagramViewModel(Dispatcher dispatcher, NavigationService navigationService, Uri url)
            : base(dispatcher, navigationService)
        {
            UserIdText = "{user-id}:";
            UserId2Text = "{id}:";
            MediaIdText = "{media-id}:";
            TagNameText = "{tag-name}";
            LocationIdText = "{location-id}:";
            DistanceText = "{distance}:";
            MinTimeText = "{min_timestamp}:";
            MaxTimeText = "{max_timestamp}:";
            LngText = "{lng}:";
            LatText = "{lat}:";
            SearchText = "{search}:";
            SendCommand = new DelegateCommand(Send, CanSend);
            Url = string.Format("https://api.instagram.com/v1/users/{0}", "{user-id}");
            ApiInfo.CurentApiChanged += OnCurentApiChanged;
            _instagram = new InstagramService(new ClientData
            {
                CleintId = "dd2d483a9d424d2da0dc20c3506a6c99",
                ClientSecret = "545397b406f4449c8590b290be35a8aa",
                RedirectUrl = "http://www.google.com",
                Scope = Settings.All
            });
            _instagram.ParseCallbakUrl(url);
            UserId = _instagram.UserApi.Id;
            UserId2 = 3;
            MediaId = 555;
            TagName = "nofilter";
            LocationId = 1;
            Distance = 1000;
            MinTime = DateTime.Now;
            MaxTime = DateTime.Now;
            Lng = 2.294351;
            Lat = 48.858844;
            Search = "jack";
            IsEnabled = true;
        }

        private void OnCurentApiChanged(object sender, EventArgs eventArgs)
        {
            if (sender != null)
            {
                _apiInfo = sender as ApiInfo;
                _commandParameter = _apiInfo.CurrentApiMetod;
                if (_apiInfo.CurrentApiMetod.Contains(" (POST)") || _apiInfo.CurrentApiMetod.Contains(" (DELETE)"))
                {
                    _apiInfo.CurrentApiMetod = _apiInfo.CurrentApiMetod.Remove(_apiInfo.CurrentApiMetod.LastIndexOf(" ", StringComparison.Ordinal));
                    _apiInfo.CurrentApiMetod = _apiInfo.CurrentApiMetod.Trim();
                }
                Url = string.Format("https://api.instagram.com/v1/{0}", _apiInfo.CurrentApiMetod);
            }
        }

        #endregion

        #region Вызов API метода

        public DelegateCommand SendCommand { get; private set; }

        private async void Send(object sender)
        {
            Result = null;
            switch (_commandParameter)
            {
                case "users/{user-id}":
                    Result = JsonConvert.SerializeObject(IsEnabled ? _instagram.UserApi.Info(UserId) : await _instagram.UserApi.InfoAsync(), Formatting.Indented);
                    break;
                case "users/self/feed":
                    Result = JsonConvert.SerializeObject(_instagram.UserApi.Feed(), Formatting.Indented);
                    break;
                case "users/{user-id}/media/recent":
                    Result = JsonConvert.SerializeObject(_instagram.UserApi.Recent(UserId), Formatting.Indented);
                    break;
                case "users/self/media/liked":
                    Result = JsonConvert.SerializeObject(_instagram.UserApi.Liked(), Formatting.Indented);
                    break;
                case "users/search":
                    Result = JsonConvert.SerializeObject(_instagram.UserApi.Search(Search), Formatting.Indented);
                    break;
                case "users/{user-id}/follows":
                    Result = JsonConvert.SerializeObject(_instagram.RelationshipApi.Follows(UserId), Formatting.Indented);
                    break;
                case "users/{user-id}/followed-by":
                    Result = JsonConvert.SerializeObject(_instagram.RelationshipApi.FollowedBy(UserId), Formatting.Indented);
                    break;
                case "users/self/requested-by":
                    Result = JsonConvert.SerializeObject(_instagram.RelationshipApi.RequestedBy(), Formatting.Indented);
                    break;
                case "users/{user-id}/relationship":
                    Result = JsonConvert.SerializeObject(_instagram.RelationshipApi.Relationship(UserId), Formatting.Indented);
                    break;
                case "users/{user-id}/relationship (POST)":
                    _instagram.RelationshipApi.Relationship(Actions.Follow, HttpMethod.Post, _instagram.UserApi.Id);
                    Result = null;
                    break;
                case "media/{id}":
                    Result = JsonConvert.SerializeObject(_instagram.MediaApi.Media(UserId), Formatting.Indented);
                    break;
                case "media/search":
                    Result = JsonConvert.SerializeObject(_instagram.MediaApi.Search(Distance, Lat, Lng), Formatting.Indented);
                    break;
                case "media/popular":
                    Result = JsonConvert.SerializeObject(_instagram.MediaApi.Popular(), Formatting.Indented);
                    break;
                case "media/{media-id}/comments":
                    Result = JsonConvert.SerializeObject(_instagram.CommentApi.Comments(MediaId), Formatting.Indented);
                    break;
                case "media/{media-id}/comments (POST)":
                    _instagram.CommentApi.Comments(MediaId);
                    Result = null;
                    break;
                case "media/{media-id}/comments/{comment-id} (DELETE)":
                    _instagram.CommentApi.Comments(MediaId);
                    Result = null;
                    break;
                case "media/{media-id}/likes":
                    Result = JsonConvert.SerializeObject(_instagram.LikeApi.Get(MediaId), Formatting.Indented);
                    break;
                case "media/{media-id}/likes (POST)":
                    _instagram.LikeApi.Post(MediaId);
                    Result = null;
                    break;
                case "media/{media-id}/likes (DELETE)":
                    _instagram.LikeApi.Delete(MediaId);
                    Result = null;
                    break;
                case "tags/{tag-name}":
                    Result = JsonConvert.SerializeObject(_instagram.TagApi.Get(TagName), Formatting.Indented);
                    break;
                case "tags/{tag-name}/media/recent":
                    Result = JsonConvert.SerializeObject(_instagram.TagApi.Recent(Search), Formatting.Indented);
                    break;
                case "tags/search":
                    Result = JsonConvert.SerializeObject(_instagram.TagApi.Search(Search), Formatting.Indented);
                    break;
                case "locations/{location-id}":
                    Result = JsonConvert.SerializeObject(_instagram.LocationApi.Get(LocationId), Formatting.Indented);
                    break;
                case "locations/{location-id}/media/recent":
                    Result = JsonConvert.SerializeObject(_instagram.LocationApi.Recent(LocationId), Formatting.Indented);
                    break;
                case "locations/search":
                    Result = JsonConvert.SerializeObject(_instagram.LocationApi.Search(Distance, Lat, Lng), Formatting.Indented);
                    break;
            }
        }

        private bool CanSend(object sender)
        {
            return true;
        }

        #endregion
    }
}